package ar.com.age.distribuidora.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import ar.com.age.distribuidora.dao.FacturaCompraDao;
import ar.com.age.distribuidora.dao.PagoChequeDao;
import ar.com.age.distribuidora.dao.PagoEfectivoDao;
import ar.com.age.distribuidora.dominio.FacturaCompra;
import ar.com.age.distribuidora.dominio.LoteDeCompra;
import ar.com.age.distribuidora.dominio.Pago;
import ar.com.age.distribuidora.dominio.PagoCheque;
import ar.com.age.distribuidora.dominio.PagoEfectivo;
import ar.com.age.distribuidora.service.CompraService;
import ar.com.age.distribuidora.service.LoteDeCompraService;

public class CompraServiceImpl implements CompraService {

	private PagoChequeDao pagoChequeDao;
	
	private PagoEfectivoDao pagoEfectivoDao;
	
	private FacturaCompraDao facturaCompraDao;
	
	private LoteDeCompraService loteDeCompraService;

	
	@Autowired(required = true)
	public void setPagoChequeDao(PagoChequeDao pagoChequeDao) {
		this.pagoChequeDao = pagoChequeDao;
	}
    
    @Autowired(required = true)
	public void setPagoEfectivoDao(PagoEfectivoDao pagoEfectivoDao) {
		this.pagoEfectivoDao = pagoEfectivoDao;
	}
    
    @Autowired(required = true)
	public void setFacturaCompraDao(FacturaCompraDao facturaCompraDao) {
		this.facturaCompraDao = facturaCompraDao;
	}
    
    // Pago Cheque
    @Override
	public void crearOEditarPagoCheque(PagoCheque pagoCheque) {
		
    	if (pagoCheque.getId() == null) {
			pagoCheque.setMonto(pagoCheque.getCheque().getMonto());
		}
    	
    	pagoChequeDao.saveOrUpdate(pagoCheque);		
	}

	@Override
	public List<Pago> buscarTodosPagoCheque() {

		return pagoChequeDao.getAll();
	}
	
	@Override
	public List<Pago> buscarDisponiblesPagoCheque() {

		return pagoChequeDao.getAvailable();
	}
	
	@Override
	public void eliminarPagoCheque(PagoCheque pagoCheque) {
		
		pagoChequeDao.physicalDelete(pagoCheque);
	}
	
	@Override
	public List<PagoCheque> buscarPagoCheque(String codigo, String estado, Date desde, Date hasta, String cheque) {

		return pagoChequeDao.find(codigo, estado, desde, hasta, cheque);
	}
	
	// Pago Efectivo
	@Override
	public void crearOEditarPagoEfectivo(PagoEfectivo pagoEfectivo) {
		
		pagoEfectivoDao.saveOrUpdate(pagoEfectivo);		
	}

	@Override
	public List<Pago> buscarTodosPagoEfectivo() {

		return pagoEfectivoDao.getAll();
	}
	
	@Override
	public List<Pago> buscarDisponiblesPagoEfectivo() {

		return pagoEfectivoDao.getAvailable();
	}
	
	@Override
	public void eliminarPagoEfectivo(PagoEfectivo pagoEfectivo) {
		
		pagoEfectivoDao.physicalDelete(pagoEfectivo);
	}
	
	@Override
	public List<PagoEfectivo> buscarPagoEfectivo(String codigo, String estado, Date desde, Date hasta) {

		return pagoEfectivoDao.find(codigo, estado, desde, hasta);
	}
	
	// Factura Compra
	@Override
	public void crearOEditarFacturaCompra(FacturaCompra facturaCompra) {
		
		facturaCompraDao.saveOrUpdate(facturaCompra);		
	}

	@Override
	public List<FacturaCompra> buscarTodosFacturaCompra() {

		return facturaCompraDao.getAll();
	}
	
	@Override
	public void eliminarFacturaCompra(FacturaCompra facturaCompra) {
		
		facturaCompraDao.physicalDelete(facturaCompra);
	}
	
	@Override
	public List<FacturaCompra> buscarFacturaCompra(String estado, String codigo, String tipo, Date desde, Date hasta) {

		List<FacturaCompra> facturas = facturaCompraDao.find(estado, codigo, tipo, desde, hasta);
		List<FacturaCompra> facturasCompletas = new ArrayList<FacturaCompra>();
		
		for(FacturaCompra fv : facturas){
			
			facturasCompletas.add(this.getFacturaCompraConListas(fv));
		}
		
		return facturasCompletas;
	}
	
	@Override
	public Double retornarSaldoAdeudado(FacturaCompra facturaCompra){
		
		// Retorna lo que falta pagar de la factura
		// saldoPagado va a ser la suma de todos los pagos
		Double saldoPagado = new Double(0.0);
		for(Pago pago : facturaCompra.getPagos()){
			
			saldoPagado = saldoPagado + pago.getMonto();
		}
		
		// Retorno la resta del saldo total a pagar de la factura menos todo lo que ya se pago
		return facturaCompra.getTotal() - saldoPagado;
	}
	
	@Override
	public void agregarPagoEfectivoAFacturaCompra(FacturaCompra facturaCompra, PagoEfectivo pago) {
		
		// Registro el nuevo pago
		this.crearOEditarPagoEfectivo(pago);
		
		// Lo agrego a la lista de pagos de la factura
		facturaCompra.agregarPago(pago);
		
		// Calculo si ya se saldo la factura para cambiar el estado
		if(this.retornarSaldoAdeudado(facturaCompra) == 0.0){
			
			facturaCompra.setEstado("Pagada");
		}
		
		// Actualizo la factura
		this.crearOEditarFacturaCompra(facturaCompra);
	}
	
	@Override
	public void agregarPagoChequeAFacturaCompra(FacturaCompra facturaCompra, PagoCheque pago) {
		
		// Registro el nuevo pago
		this.crearOEditarPagoCheque(pago);
		
		// Lo agrego a la lista de pagos de la factura
		facturaCompra.agregarPago(pago);
		
		// Calculo si ya se saldo la factura para cambiar el estado
		if(this.retornarSaldoAdeudado(facturaCompra) == 0.0){
			
			facturaCompra.setEstado("Pagada");
		}
		
		// Actualizo la factura
		this.crearOEditarFacturaCompra(facturaCompra);
	}
	
	@Override
	public void agregarLoteDeCompraAFacturaCompra(FacturaCompra facturaCompra, LoteDeCompra lote) {
		
		// Registro el nuevo lote de compra en una Factura ya registrada en la BD
		loteDeCompraService.crearOEditar(lote);
		
		// Lo agrego a la lista de lineas de la factura
		facturaCompra.agregarLoteDeCompra(lote);
		
		// Actualizo el saldo de la factura
		facturaCompra.setTotal(facturaCompra.getTotal() + (lote.getCantidadDeCompra() * lote.getPrecioDeCompra()));

		// Actualizo la factura
		this.crearOEditarFacturaCompra(facturaCompra);
	}


	@Override
	public void actualizarTotal(FacturaCompra facturaCompra){	

		Double total = new Double(0.0);
		for(LoteDeCompra lote : facturaCompra.getLotesDeComra()){
			total = total + (lote.getCantidadDeCompra()*lote.getPrecioDeCompra());
		}
		facturaCompra.setTotal(total);

	}	

	@Override
	public FacturaCompra retornarFacturaCompraConLotes(FacturaCompra factura) {
		
		return facturaCompraDao.getFacturaCompraConLotes(factura);
	}
	
	@Override
	public FacturaCompra retornarFacturaCompraConPagos(FacturaCompra factura) {
		
		return facturaCompraDao.getFacturaCompraConPagos(factura);
	}
	
	@Override
	public FacturaCompra getFacturaCompraConListas(FacturaCompra factura) {

		return facturaCompraDao.getFacturaCompraConListas(factura);
	}
	
	// Informes
	@Override
	public List<FacturaCompra> getFacturasInformes(String producto, String proveedor, Date desde, Date hasta) {

		List<FacturaCompra> facturas = facturaCompraDao.getFacturasInformes(proveedor, desde, hasta);
		List<FacturaCompra> facturasConListas = new ArrayList<FacturaCompra>(); 
		List<FacturaCompra> facturasInformes = new ArrayList<FacturaCompra>();
		
		for(FacturaCompra f : facturas) {
			facturasConListas.add(facturaCompraDao.getFacturaCompraConLotes(f));
		}

		// Filitrar por Productos
		if(producto != "") {

			for(FacturaCompra f : facturasConListas) {

				// Recorro la lista de Lineas de Factura
				for(LoteDeCompra lote : f.getLotesDeComra()) {
					if(lote.getProducto().getCodigo().equals(producto)) {

						facturasInformes.add(f);
						break;
					}
				}
			}
		}
		else {
			// Todas las facturas
			facturasInformes = facturasConListas;
		}

		return facturasInformes;
	}
}
